﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition.Hosting;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Configuration;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.IO;
using System.Linq;
using System.Reflection;
using SalesSys.Comm.Utility;
using SalesSys.DAL.Base;
using SalesSys.DAL.Models;

namespace SalesSys.DAL
{
    public class WXDbContext : DbContext
    {
        public static void Init()
        {
         Database.SetInitializer<WXDbContext>(null);
        }

        public readonly string LinkString;
        public WXDbContext():base("name=WXDB")
        {
            LinkString = "WXDB";
        }

        public class StrLenConvention : Convention
        {
            public StrLenConvention()
            {
                this.Properties<string>().Configure(p=>p.HasMaxLength(255));
            }
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {

            modelBuilder.Conventions.Add<StrLenConvention>();
            modelBuilder.Properties().Where(p => p.GetCustomAttributes(typeof(DecimalPrecisionAttribute), false).OfType<DecimalPrecisionAttribute>().Any())
            .Configure(m => m.HasPrecision(m.ClrPropertyInfo.GetCustomAttributes(false).OfType<DecimalPrecisionAttribute>().First().Precision,
            m.ClrPropertyInfo.GetCustomAttributes(typeof(DecimalPrecisionAttribute), false).OfType<DecimalPrecisionAttribute>().First().Scale));
            //modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
         //   modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
            //modelBuilder.Conventions.Remove<OneToOneConstraintIntroductionConvention>();         
          // EFAutoMapCfg.AutoLoadMapCfg<IEntityMapConfig>(modelBuilder);

           //var map = new SysModelMap(); 
           //map.RegCfg(modelBuilder.Configurations);
           //WXCfgMap.RegCfg(modelBuilder.Configurations);
           //MallCfgMap.ToRegCfg(modelBuilder.Configurations);
           //PartnerMapCfg.SetCfg(modelBuilder.Configurations);
           SetCfg(modelBuilder.Configurations);
            if (DbModelCreatingReg!=null)
            {
                try
                {
                    DbModelCreatingReg(modelBuilder.Configurations);
                }
                catch (Exception ex)
                {
                    Log.m.Critical("系统初始化dbContext事件异常！"+ ex);
                    throw;
                }
               
            }
        }
       public static event Action<ConfigurationRegistrar> DbModelCreatingReg;
        //public DbSet<CourseCatalog> CouseTypeSet { get; set; }

        public static IEnumerable<ICustomRegMapCfg> SetCfg(ConfigurationRegistrar reg)
        {
            var path =AppRunInfo.GetBinDir();
            var dir = new DirectoryCatalog(path, "SalesSys.*.dll");
            CompositionContainer container = new CompositionContainer(dir);
            //var filteredCat = new FilteredCatalog(ass,p=>p.Metadata[]
            IEnumerable<ICustomRegMapCfg> maps = container.GetExportedValues<ICustomRegMapCfg>();//"AutoLoadMap"
            maps.ToList().ForEach(p => p.RegCfg(reg));
            return maps;
        }


    }

    [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
    public class DecimalPrecisionAttribute : System.Attribute
    {
        public byte Precision = 18;
        public byte Scale = 2;

        public DecimalPrecisionAttribute(byte precision = 18, byte scale = 2)
        {
            Precision = precision;
            Scale = scale;
            if (Precision < 1 || Precision > 38)
            {
                Log.m.Critical("精度必须在1和38之间.");
            }
            if (Scale < 1 || Scale > 38)
            {
                Log.m.Critical("刻度必须在1和38之间.");
            }
        }
    }
}
